/*
 * Galaxium Messenger
 * Copyright (C) 2007 Ben Motmans <ben.motmans@gmail.com>
 * 
 * License: GNU General Public License (GPL)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Collections.Generic;

using Anculus.Core;
using Galaxium.Core;

namespace Galaxium.Protocol
{
	public abstract class AbstractConnection : IConnection
	{
		public event EventHandler<ConnectionEventArgs> Established;
		public event EventHandler<ConnectionEventArgs> Closed;
		public event EventHandler<ConnectionEventArgs> AfterConnect;
		public event EventHandler<ConnectionErrorEventArgs> ErrorOccurred;
		public event EventHandler<ConnectionDataEventArgs> DataReceived;
		public event EventHandler SendComplete;
		
		protected ISession _session;
		protected IConnectionInfo _connectionInfo;
		
		protected bool _intendedDisconnect;
		protected bool _disposed;

		protected object _lock = new object ();
		
		public abstract bool IsSending { get; }

		protected AbstractConnection (ISession session, IConnectionInfo connectionInfo)
		{
			ThrowUtility.ThrowIfNull ("session", session);
			ThrowUtility.ThrowIfNull ("connectionInfo", connectionInfo);

			this._session = session;
			this._connectionInfo = connectionInfo;

		}

		public ISession Session
		{
			get { return _session; }
		}

		public IConnectionInfo ConnectionInfo
		{
			get { return _connectionInfo; }
			set { _connectionInfo = value; }
		}

		public abstract bool IsConnected { get; }

		public abstract void Connect ();

		public abstract void Reconnect ();
		
		public abstract void Disconnect ();
		
		public void Dispose ()
		{
			Dispose (true);
			GC.SuppressFinalize (this);
		}
		
		protected virtual void Dispose (bool disposing)
		{
			
		}
		
		internal static IPEndPoint GetAddress (string hostName, int port)
		{
			//work around for a bug in the .NET framework
			//http://msdn2.microsoft.com/en-us/library/ms143998.aspx
			IPAddress address = null;
			
			if (IPAddress.TryParse (hostName, out address))
			{
				return new IPEndPoint (address, port);
			}
			else
			{
				IPHostEntry hostInfo = Dns.GetHostEntry (hostName);
				return new IPEndPoint (hostInfo.AddressList[0], port);
			}
		}

		public virtual void Send (byte[] data)
		{
			
		}
		
		protected virtual void OnDataReceived (ConnectionDataEventArgs args)
		{
			if (DataReceived != null)
				DataReceived (this, args);
		}
		
		protected virtual void OnSendComplete (EventArgs args)
		{
			if (SendComplete != null)
				SendComplete (this, args);
		}
		
		protected virtual void OnEstablished (ConnectionEventArgs args)
		{
			if (Established != null)
				Established (this, args);
		}
		
		protected virtual void OnAfterConnect (ConnectionEventArgs args)
		{
			if (AfterConnect != null)
				AfterConnect (this, args);
		}
		
		protected virtual void OnClosed (ConnectionEventArgs args)
		{
			if (Closed != null)
				Closed (this, args);
		}

		protected virtual void OnErrorOccurred (ConnectionErrorEventArgs args)
		{
			if (ErrorOccurred != null)
				ErrorOccurred (this, args);
		}
	}
}